package com.bodu.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.bodu.core.entity.ParamReq;
import com.bodu.core.entity.enums.StatusFlagEnum;
import com.bodu.core.entity.result.Result;
import com.bodu.core.task.QuartzTaskBean;
import com.bodu.system.entity.po.CronTriggersPo;
import com.bodu.system.entity.po.CronTriggersSynchroTimePo;
import com.bodu.system.entity.request.CronTriggersRequest;
import com.bodu.system.entity.vo.CronTriggersVo;
import com.bodu.system.mapper.CronTriggersMapper;
import com.bodu.system.mapper.CronTriggersSynchroTimeMapper;
import com.bodu.system.service.CronTriggersService;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 定时器 Service impl
 *
 * @author Administrator
 */
@Service
public class CronTriggersServiceImpl implements CronTriggersService {

    @Resource
    private CronTriggersMapper cronTriggersMapper;

    private final QuartzTaskBean quartzTaskBean;

    @Resource
    private CronTriggersSynchroTimeMapper cronTriggersSynchroTimeMapper;

    public CronTriggersServiceImpl(QuartzTaskBean quartzTaskBean) {
        this.quartzTaskBean = quartzTaskBean;
    }

    @Override
    public CronTriggersVo getModel(Long id) {
        CronTriggersVo cronTriggersVo = new CronTriggersVo();
        CronTriggersPo cronTriggersPo = cronTriggersMapper.getModel(id);
        BeanUtils.copyProperties(cronTriggersPo, cronTriggersVo);
        cronTriggersVo.setStatus(cronTriggersPo.getStatusFlag().equals(StatusFlagEnum.USE.getValue()) ? true : false);
        return cronTriggersVo;
    }

    @Transactional
    @Override
    public Long save(CronTriggersRequest request) {
        request.setStatusFlag(StatusFlagEnum.UN_USE.getValue());
        return cronTriggersMapper.save(request);
    }

    @Transactional
    @Override
    public Long update(CronTriggersRequest request) {
        cronTriggersMapper.update(request);

        // 开启
        if (ObjectUtil.equal(request.getStatusFlag(), StatusFlagEnum.USE.getValue())) {
            try {
                operScheduleJob(request.getId(), StatusFlagEnum.USE.getValue());
            } catch (SchedulerException e) {
                throw new RuntimeException(e);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
        return request.getId();
    }

    @Override
    public List<CronTriggersVo> listPage(ParamReq<CronTriggersRequest> params) {
        List<CronTriggersVo> res = cronTriggersMapper.listPage(params);
        for (CronTriggersVo cronTriggersPo : res) {
            cronTriggersPo.setStatus(cronTriggersPo.getStatusFlag().equals(StatusFlagEnum.USE.getValue()));
            CronTriggersSynchroTimePo ctstp = cronTriggersSynchroTimeMapper.getLastModelByClass(cronTriggersPo.getCronTriggersClass());
            if (ObjectUtil.isNotEmpty(ctstp)) {
                cronTriggersPo.setLastExecTime(ctstp.getEntTime());
            }
        }
        return res;
    }

    @Override
    public Integer countPage(ParamReq<CronTriggersRequest> params) {
        return cronTriggersMapper.countPage(params);
    }

    @Override
    public Integer updateDelFlagById(Long id, Integer delFlag) {
        try {
            quartzTaskBean.deleteScheduleJob(id + "");
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
        return cronTriggersMapper.updateDelFlagById(id, delFlag);
    }

    @Override
    public Result<Integer> switchStatus(CronTriggersRequest request) {
        Integer statusFlag = request.getStatusFlag();

        Long id = request.getId();
        Integer res = cronTriggersMapper.updateStatusFlagById(id, statusFlag);

        try {
            operScheduleJob(id, statusFlag);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return Result.success(res);
    }

    @Override
    public CronTriggersVo getModelByCronClassName(String className) {
        CronTriggersPo cronTriggersPo = cronTriggersMapper.getModelByCronClassName(className);
        if (ObjectUtil.isEmpty(cronTriggersPo)) {
            return null;
        }
        CronTriggersVo cronTriggersVo = new CronTriggersVo();
        BeanUtils.copyProperties(cronTriggersPo, cronTriggersVo);
        return cronTriggersVo;
    }

    /**
     * 更新定时任务
     *
     * @param id
     * @param statusFlag
     * @throws SchedulerException
     * @throws ClassNotFoundException
     */
    private void operScheduleJob(Long id, Integer statusFlag) throws SchedulerException, ClassNotFoundException {
        if (ObjectUtil.equal(statusFlag, StatusFlagEnum.USE.getValue())) {
            CronTriggersVo cron = getModel(id);
            quartzTaskBean.deleteScheduleJob(id + "");
            quartzTaskBean.createScheduleJob(cron);
        } else {
            quartzTaskBean.pauseScheduleJob(id + "");
        }
    }
}
